﻿/** 自制的UI类(utf-8 with BOM)
  包括界面设定和热键对应的宏的随时选择
  还定义了2个接口
  由于需要传入各种参数才能使用,所以设定成了需要新建实例才能使用的方式
  
  By setycyas @2023-02-01
*/

;** 库调用
#Include D:\software\AutoHotkey\MyAHK\MyAhkClass\MyFuns.class.ahk

class MyUI {

  ;实例变量
  ;**用于记录绑定组件的全局变量的名称的变量
  _exeComboBoxVar := "" ;记录设定exe的comboBox所绑定的变量的名字
  _macroComboBoxVars := [] ;记录设定macro的comboBox所绑定的变量的名字的数组
  ;*重要!接口打包在实例变量中,在构造函数中定义接口
  ;目前接口包括:customGui(),onSubmit(this)
  _interface := {customGui: "", onSubmit: ""}

  ;构建窗口的主函数,执行后立即创建窗口
  ;title是窗口标题
  ;exeList是可能选择的exe字符串表,用于gui组件,按组件格式写,如WinKawaks.exe|X-Zone.exe|fbas.exe|Nebula.exe
  ;macroList是宏名称字符串表,用于gui组件,按组件格式写,如"空|下前A|下上A|下B|下前B|前A|A后防御"
  ;hotkeys是使用的热键的数组[]
  ;preset是预设{},,每一项如:preset["龙2"] := ["下前A", "下上A", "A后防御", "下前B"],长度必须与_hotkeys相同
  ;interface是实现接口的函数名{},需要实现的接口见前面的实例变量定义
  __New(title, exeList, macroList, hotkeys, preset, interface){
    local randomID := "u" . MyFuns.getRandomStr(8) ;一个随机ID,用于掺入绑定组件的变量名当中,避免撞车
    local k, v ;循环用临时变量
    local guiVar ;绑定组件的变量名临时变量
	local keyName ;热键名临时变量
    local funcName ;函数名临时对象
    local funcObj ;函数对象临时变量
    this._hotkeys := hotkeys
    this._preset := preset
    this._interface := interface
    this._submitTimes := 0
    ;设置绑定组件的变量的名字
    this._exeComboBoxVar := randomID . "exe"
    loop, % hotkeys.Count() {
      this._macroComboBoxVars.push(randomID . "macro" . A_Index)
    }
    ;*创建窗口
    Gui, New, , % title
    Gui, Add, Tab3, , 初始设定|热键设定|自定义 ;标签页分组
    Gui, Tab, 初始设定
    ;exe选择
    guiVar := this._exeComboBoxVar
    Gui, Add, Text, x+20 y+20, 选择exe：
    Gui, Add, ComboBox, xp+80 yp-3 W100 v%guiVar% choose1, % exeList
    Gui, Tab, 热键设定
    ;宏绑定ComboBox组
    loop, % this._hotkeys.Count() {
	  keyName := this._hotkeys[A_Index]
      guiVar :=  this._macroComboBoxVars[A_Index]
      if (A_Index == 1) {
        Gui, Add, Text, x+20 y+20, %keyName%键：
      } else {
        Gui, Add, Text, xp-80 yp+30, %keyName%键：
      }
      Gui, Add, ComboBox, xp+80 yp-3 W100 v%guiVar% choose1, % macroList
	}
    Gui, Tab, 自定义
	;重要!设置自定义Gui组件的接口
    funcName := this._interface["customGui"]
	if (IsFunc(funcName)){
	  %funcName%()
	}
    Gui, Tab
    ;提交数据按钮
    funcObj := this._ButtonSubmit.bind(this)
    guiVar :=  randomID . "buttonSubmit"
    Gui, Add, Button, v%guiVar%, 提交
    GuiControl +g, %guiVar%, % funcObj
    ;预设菜单
    funcObj := this.MenuReadPreset.bind(this)
    for k, v in this._preset {
      ;每一个预设制作一个菜单项,名字为PresetMenuItem,点击时执行this.MenuReadPreset函数
      Menu, PresetMenuItem, Add, %k%, % funcObj
    }
    Menu, PresetMenuBar, Add, 读取预设, :PresetMenuItem ;制作菜单,并让所有名为PresetMenuItem的菜单项加入
    Gui, Menu, PresetMenuBar ;加入菜单
    ;加入状态栏
    Gui, Add, StatusBar, , 未设定热键
    ;显示gui
    Gui, Show, X1136 Y353
	Gui, +AlwaysOnTop
  }

  ;** gui响应
  ;提交数据时的行动,并不绑定到gui按钮,因为可能有多种提交方式.属于可供外部调用的函数
  submit_(){
    local funcName ;函数名临时变量
    Gui, Submit, NoHide
	;首次设置,一些基础设定只能设置一次,设置后禁用
	if (this._submitTimes == 0){
	  GuiControl, Disable, % this._exeComboBoxVar
	}
	this._setMacros() ;重新设置热键对应的宏
	this._submitTimes += 1
    SB_SetText(A_Hour . ":" . A_Min . ":" . A_Sec . " 提交")
	;重要!提交数据后的接口
    funcName := this._interface["onSubmit"]
	if (IsFunc(funcName)){
	  %funcName%(this)
	}
  }

  ;提交数据按钮
  _ButtonSubmit(){
    this.submit_()
    MsgBox, 数据提交成功!
  }
  
  ;读取预设,把各个技能的ComboBox修改成预设值但不提交数据,这个可供外部调用
  MenuReadPreset(ItemName){
    local guiVar
    loop, % this._hotkeys.Count() {
      guiVar := this._macroComboBoxVars[A_Index]
      GuiControl, ChooseString, %guiVar%, % this._preset[ItemName][A_INDEX]
    }
    SB_SetText(A_Hour . ":" . A_Min . ":" . A_Sec . " 读取预设 - " . ItemName)
  }

  ;**设置热键对应的宏
  _setMacros(){
    local winTitle
    local keyName ;宏热键命临时变量
	local macroName ;宏热键命临时变量
    winTitle := "ahk_exe " . MyFuns.getVarValue(this._exeComboBoxVar)
    loop, % this._hotkeys.Count() {
      macroName := MyFuns.getVarValue(this._macroComboBoxVars[A_Index])
      keyName := this._hotkeys[A_Index]
      MyFuns.setHotkey(keyName, macroName, winTitle)
    }
  }

}
